﻿@namespace Masa.Tsc.Web.Admin.Rcl.Components
@inherits TscComponentBase

<SSheetDialog Value="_dialogValue" ValueChanged="DialogValueChanged" ContentLoading="_loading" Title="@_treeData.FirstOrDefault()?.Resource?[TraceKeyConst.Resource.ServiceName]?.ToString()">
    <div class="d-flex">
        <div class="pa-12" style="width:100%">
            <div class="d-flex mb-6">
                <SearchTextField FullWidth Small Clearable Class="my-auto mr-6" Style="max-width:300px;display:none" />
                <MSpacer></MSpacer>
                @if (_treeData.Any())
                {
                    <div class="d-flex align-center">
                        <div class="mr-6">
                            <MChip Label Small Color="emphasis2 mr-3" Dark>@I18n.Trace("Start")</MChip>
                            <span class="regular--text">@(_treeData[0].Timestamp + CurrentTimeZone.BaseUtcOffset)</span>
                        </div>
                        <div class="mr-6">
                            <MChip Label Small Color="emphasis2 mr-3" Dark>@I18n.Trace("Duration")</MChip>
                            <span class="regular--text">@FormatDuration(_totalDuration)</span>
                        </div>
                        <div>
                            <MChip Label Small Color="emphasis2 mr-3" Dark>@I18n.Trace("Span Count")</MChip>
                            <span class="regular--text">@_count</span>
                        </div>
                    </div>
                }
            </div>

            <div class="overflow-y" style="max-height:300px">
                @foreach (var timelineView in _timelineView)
                {
                    double sumLeft = 0;
                    double sumWidth = 0;
                    <div class="trace-timelines mb-2 overflow-x-hidden">
                        @foreach (var timeline in timelineView)
                        {
                            bool isSelected = timeline.Id == _activeTreeItem.SpanId;
                            if (timeline.marginLeft > 0)
                            {
                                <div class="trace-timeline__section" style="width: @((timeline.marginLeft - sumLeft) * 100)%">
                                    <div class="trace-timeline__background">
                                    </div>
                                </div>
                            }
                            <div class="trace-timeline__section" style="width: @(timeline.Percent * 100)%;">
                                <div class="trace-timeline__background">
                                    <div class="trace-timeline__leaner @(timeline.Render ? "" : "d-none") @(isSelected?"yellow":"")"></div>
                                </div>
                            </div>
                            sumWidth += (timeline.marginLeft - sumLeft) + timeline.Percent;
                            sumLeft = timeline.marginLeft + timeline.Percent;
                        }
                        @if (sumWidth < 1)
                        {
                            <div class="trace-timeline__section" style="width: @((1 - sumWidth) * 100)%">
                                <div class="trace-timeline__background">
                                </div>
                            </div>
                        }
                    </div>
                }
            </div>

            @if (_treeData.Any())
            {
                var sections = NumberSplit(_totalDuration);
                var avgPercentage = 100.0 / (sections.Count + 1);

                <div class="trace-timelines-view mb-6">
                    <div class="trace-timelines-view__line">
                        <div class="trace-timelines-view__line-item body2" style="left: 0;">0</div>
                        @for (var i = 0; i < sections.Count; i++)
                        {
                            var left = avgPercentage * (i + 1);
                            <div class="trace-timelines-view__line-item body2" style="left: @(left)%;">@(FormatDuration(sections[i]))</div>
                        }
                        <div class="trace-timelines-view__line-item body2" style="right: 0;">@FormatDuration(_totalDuration)</div>
                    </div>
                </div>
            }
            <MTreeview Items="@_treeData"
                       ItemChildren="item => item.Children?.Any() ?? false ? item.Children : default!"
                       ItemText="item => item.Name"
                       ItemKey="item => item.SpanId"
                       TItem="TraceResponseTree"
                       TKey="string"
                       OpenAll
                       Activatable
                       @bind-Active="_actives"
                       OnActiveUpdate="OnActiveUpdate"
                       Class="flex-fill overflow-y-auto"
                       Style='@($"height: calc(100vh - {(_timelineView.Count-15>0? 300:_timelineView.Count*20) + 254}px)")'
                       @key="@_treeData">
                <LabelContent>
                    <MTooltip Left Top Context="tooltipContent">
                        <ActivatorContent>
                            <div style="max-width:1000px;white-space:nowrap" class="d-flex justify-start">
                                <div @attributes="@tooltipContent.Attrs" class="text-truncate pt-1">@context.Item.Name</div>
                                @((RenderFragment)(labelBuilder => RenderItemLabel(labelBuilder, context.Item)))
                            </div>
                        </ActivatorContent>
                        <ChildContent>
                            <span>@context.Item.Name</span>
                        </ChildContent>
                    </MTooltip>
                </LabelContent>
                <AppendContent>
                </AppendContent>
            </MTreeview>
        </div>

        <MDivider Vertical Class="mx-0" Style="height:100vh" />

        @if (_activeTreeItem is not null)
        {
            var detail = _activeTreeItem.ToDictionary(nameof(TraceResponseTree.Children), nameof(TraceResponseTree.Attributes), nameof(TraceResponseTree.Resource), nameof(TraceResponseTree.Timelines), nameof(TraceResponseTree.Level), nameof(TraceResponseTree.Duration));
            <div class="pa-12">
                <MList Flat Class="mb-4 rounded tracedetail" style="width:382px">
                    <MListItem>
                        <MListItemContent>
                            <MListItemTitle>
                                @I18n.Trace(TraceKeyConst.Resource.ServiceName)
                            </MListItemTitle>
                            <MListItemSubtitle>
                                @if (!_activeTreeItem.Resource.TryGetValue(TraceKeyConst.Resource.ServiceName, out var serviceName))
                                {
                                    serviceName = "- -";
                                }
                                <TooltipCopy Value="@serviceName" TextClass="text-lg-h6 copy_text"
                                             IconClass="icon_large"
                                             IconHoverClass="icon_large_hover"></TooltipCopy>
                            </MListItemSubtitle>
                        </MListItemContent>
                    </MListItem>
                    <MListItem>
                        <MListItemContent>
                            <MListItemTitle>@I18n.Trace(TraceKeyConst.Attributes.Target)</MListItemTitle>
                            <MListItemSubtitle>
                                <div class="d-flex flex-row">
                                    <div class="flex-column col-6">
                                        @if (!_activeTreeItem.Attributes.TryGetValue(TraceKeyConst.Attributes.Target, out var target))
                                        {
                                            target = "- -";
                                        }
                                        <TooltipCopy Value="@target" TextClass="text-lg-h6 copy_text"
                                                     IconClass="icon_large"
                                                     IconHoverClass="icon_large_hover"></TooltipCopy>
                                    </div>
                                    @if (!string.Equals(target, "- -"))
                                    {
                                        <div class="d-flex flex-row col-6 justify-space-between">
                                            <MButton Icon Text Class="flex-column pa-0" MinWidth="32"> <SIcon @onclick="async ()=>await NextAsync(false)" Size="32" Tooltip="@I18n.Trace("Prev")">mdi-chevron-left</SIcon></MButton>
                                            <MButton Icon Text Class="flex-column pa-0 ml-4" MinWidth="32"><SIcon @onclick="async ()=>await NextAsync()" Size="32" Tooltip="@I18n.Trace("Next")">mdi-chevron-right</SIcon></MButton>
                                        </div>
                                    }
                                </div>
                            </MListItemSubtitle>
                        </MListItemContent>
                    </MListItem>
                </MList>
                <div class="trace_detail" style="width:382px">
                    <MTabs Value="_tabValue" ValueChanged="OnTabValueChange" ShowArrows="false">
                        <MTab>@($"{I18n.Trace("Attribute")}({_activeTreeItem.Attributes.Count})")</MTab>
                        <MTab>@($"{I18n.Trace("Resource")}({_activeTreeItem.Resource.Count})")</MTab>
                        <MTab>@($"{I18n.Trace("Detail")}({detail.Count})")</MTab>
                        <MTab>@($"{I18n.Log("Log")}{(_logsCount == null ? "" : "(" + _logsCount + ")")}")</MTab>
                    </MTabs>
                    <MTabsItems @bind-Value="_tabValue">
                        <MTabItem>
                            @((RenderFragment)(dictRender => RenderDictionary(dictRender, _activeTreeItem.Attributes)))
                        </MTabItem>
                        <MTabItem>
                            @((RenderFragment)(dictRender => RenderDictionary(dictRender, _activeTreeItem.Resource)))
                        </MTabItem>
                        <MTabItem>
                            @((RenderFragment)(dictRender => RenderDictionary(dictRender, detail)))
                        </MTabItem>
                        <MTabItem>
                            @if (_loadLogs)
                            {
                                <MProgressLinear Indeterminate Color="primary"></MProgressLinear>
                            }
                            else
                            {
                                <MCard Style="overflow-x-hidden" Height="600">
                                    <MVirtualScroll OverscanCount=5 TItem="LogModel" Items="_logs" Class="m-sheet theme--light" Style="width:100% !important">
                                        <ItemContent>
                                            <div class="d-flex @(_logs != null && _logs.First().Equals(context)?"mt-4":"")">
                                                <div>
                                                    <LogView Small JsonObject="context.ExtensionData" />
                                                </div>
                                            </div>
                                            @if (_logs != null && !_logs.Last().Equals(context))
                                            {
                                                <MDivider Class="mb-4" />
                                            }
                                        </ItemContent>
                                    </MVirtualScroll>
                                </MCard>
                            }
                        </MTabItem>
                    </MTabsItems>
                </div>
            </div>
        }
    </div>
</SSheetDialog>

@code {

    private void RenderItemLabel(RenderTreeBuilder __builder, TraceResponseTree item)
    {
        Dictionary<string, string> labelDictionary = new();
        if (item.Attributes.TryGetValue(TraceKeyConst.Attributes.Db, out var dbName))
        {
            if (dbName is not null)
                labelDictionary.TryAdd(dbName.ToString()!, "#DCFFDB");
        }
        if (item.Attributes.ContainsKey(TraceKeyConst.Attributes.HttpKey))
        {
            labelDictionary.TryAdd("HTTP", "#FFFDD4");
        }

        if (item.Attributes.TryGetValue(TraceKeyConst.Attributes.HttpStatusCode, out object? statusCodeObj))
        {
            var statusCode = statusCodeObj?.ToString();
            if (int.TryParse(statusCode, out var code) && _errorStatus.Contains(code))
            {
                labelDictionary.TryAdd("ERROR", "#FFDBDC");
            }
        }

        foreach (var dic in labelDictionary)
        {
            <MChip Label Class="ml-3" Color="@dic.Value">@dic.Key</MChip>
        }
    }

    private void RenderDictionary(RenderTreeBuilder __builder, IDictionary<string, object> dictionary)
    {
        foreach (var item in dictionary)
        {
            string? value;
            if (item.Value is DateTime dateTime)
            {
                value = dateTime.ToString("yyyy/MM/dd HH:mm:ss.fff");
            }
            else if (item.Value is double doubleValue)
            {
                value = doubleValue.ToString("0.##");
            }
            else
            {
                value = item.Value.ToString();
            }

            <MListItem Class="pa-0">
                <MListItemContent>
                    <MListItemTitle>@item.Key</MListItemTitle>
                </MListItemContent>
                <MListItemAction Style="max-width: 38%">
                    <MListItemActionText Class="text-truncate text-right masa body-2"
                                         Style="width: 100%; cursor: auto;">
                        <TooltipCopy Value="@value" TextClass="copy_text"></TooltipCopy>
                    </MListItemActionText>
                </MListItemAction>
            </MListItem>
        }
    }
}